package tools;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ProcessBuilder.Redirect;

/**
 * Permet d'exécuter un programme C++, de lui passer des paramètres et de récupérer sa sortie standard.
 * @author Guillaume Poças
 */
public class ExecuteExternalApplication {
	
	private String savedMsg;
	
	/**
	 * Constructeur vide.
	 * @throws IOException
	 */
	public ExecuteExternalApplication() {
		this.savedMsg = "";
	}
	
	/**
	 * Méthode pour exécuter un programme externe.
	 * @param args
	 * @return valeur de retour
	 * @throws IOException
	 */
	public int execute(String[] args) throws IOException{
		//String[] args = { path, "A51", "1", "0101010101010101010101011111111111111111111110000000000000000000", size, "1101001001001011101010010010101011111111110100100100101110101001" };
		//-e A51 "C:/Documents and Settings/Guillaume/Mes documents/Visual Studio 2010/Projects/crypto_cipher/crypto_cipher/key/A51.key" 130 1101001001001011101010010010101011111111110100100100101110101001111010010010010111010100100101010111111111101001001001011101010011
		
		Runtime runtime = Runtime.getRuntime();
		final Process process = runtime.exec(args);
		
		// Consommation de la sortie standard de l'application externe dans un Thread separe
		new Thread() {
			public void run() {
				try {
					BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
					String line = "";
					try {
						while((line = reader.readLine()) != null) {
							// Traitement du flux de sortie de l'application si besoin est
							System.out.println("out: "+line);
							savedMsg = line;
						}
					} finally {
						reader.close();
					}
				} catch(IOException ioe) {
					ioe.printStackTrace();
				}
			}
		}.start();
	
		// Consommation de la sortie d'erreur de l'application externe dans un Thread separe
		new Thread() {
			public void run() {
				try {
					BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
					String line = "";
					try {
						while((line = reader.readLine()) != null) {
							// Traitement du flux d'erreur de l'application si besoin est
							System.out.println("ERROR: "+line);
						}
					} finally {
						reader.close();
					}
				} catch(IOException ioe) {
					ioe.printStackTrace();
				}
			}
		}.start();
		
		
		
		try {
			System.out.println("Threads End");
			Thread.sleep(1000);
			process.destroy();
			//Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		return process.exitValue();
	
	}
	
	/**
	 * Execute un programme externe sans attendre de sortie.
	 * @param args
	 * @throws IOException
	 * @throws InterruptedException 
	 */
	public static int executeShell(String... args) throws IOException, InterruptedException {
		Process proc = new ProcessBuilder(args)
			.redirectError(Redirect.INHERIT)
			.redirectOutput(Redirect.INHERIT).start();
		proc.waitFor();
		return proc.exitValue();
		
		//Runtime.getRuntime().exec(args);
	}
	
	public String getSavedMsg(){	return this.savedMsg;	}
	
	
	// tests
	public static void main(String[] args) throws IOException {
		String path = "C:\\Users\\B182JS\\workspace\\cryptography\\c++\\exec\\crypto_cipher.exe";
		String data = "1101001001001011101010010010101011111111110100100100101110101001111010010010010111010100100101010111111111101001001001011101010011";
		
		String A51KeyPath = "C:\\Users\\B182JS\\workspace\\cryptography\\c++\\exec\\key\\A51.key.txt";
		//String LfsrKeyPath = "C:\\Users\\B182JS\\workspace\\cryptography\\c++\\exec\\key\\Lfsr.key.txt";
		
		String size = String.valueOf(data.length());
		String[] arg = { path, "-e", "a51" ,A51KeyPath, size, data };
		
		ExecuteExternalApplication eea = new ExecuteExternalApplication();
		int out = eea.execute(arg); //LFSR...mais pas terrible pour tester
		//eea.execute(path);
		System.out.println("Sortie = "+out);
		
		if(out == 0){
			String savedMsg = eea.getSavedMsg();
			System.out.println("Message sauvé : "+savedMsg);
			System.out.println("Analyse du msg : "+savedMsg.length());
			for(int i = 0; i < savedMsg.length(); i++)	System.out.println(savedMsg.charAt(i));
			
			for(int i = 0; i < 256; i++){
				if(savedMsg.charAt(savedMsg.length()-1) == (char)i)	System.out.println("Win ! "+(char)i);
			}
			System.out.println("c: "+savedMsg.charAt(savedMsg.length()-1)+" & i: "+(int)savedMsg.charAt(savedMsg.length()-1));
			
			String realMsg = savedMsg.substring(0,(Integer.valueOf(size)));
			System.out.println(realMsg+" of size "+realMsg.length());
			//System.out.println((int)realMsg.charAt(32));
		}
	}

}
